package com.acmetelecom.call;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.acmetelecom.customer.Customer;
import com.acmetelecom.customer.CustomerUtils;

import static com.acmetelecom.call.CallEventBuilder.*;

public class CallLogger {
	
	private Map<String, List<CallStart>> startedCalls = new HashMap<String, List<CallStart>>();
	private Map<String, List<Call>> completedCalls = new HashMap<String, List<Call>>();

	public void clear() {
		startedCalls.clear();
		completedCalls.clear();
	}
	
	public void log(CallStart start) {
		getStartedCalls(start).add(start);
	}
	
	public void log(CallEnd end) {
		for(CallStart start : getStartedCalls(end)) {
			if(matches(start, end)) {
				addCompletedCall(start, end);
				startedCalls.get(getCallerNo(start)).remove(start);
				return;
			}
		}
		throw new InvalidCallEndEventException("There is no corresponding start call event for this end event");
	}

	private List<CallStart> getStartedCalls(CallEvent event) {
		if(!startedCalls.containsKey(getCallerNo(event))) {
			startedCalls.put(getCallerNo((event)), new ArrayList<CallStart>());
		}
		return startedCalls.get(getCallerNo(event));
	}

	private void addCompletedCall(CallStart start, CallEnd end) {
		getCompletedCalls(start.getCaller()).add(first(start).then(end));
	}

	private boolean matches(CallStart start, CallEnd end) {
		return CustomerUtils.areEqual(start.getCallee(), end.getCallee());
	}

	private String getCallerNo(CallEvent start) {
		return start.getCaller().getPhoneNumber();
	}
	
	/***
	 * @param customer The customer
	 * @return List of calls made by this customer that have both 
	 * started and finished.
	 */
	public List<Call> getCompletedCalls(Customer customer) {
		if(!completedCalls.containsKey(customer.getPhoneNumber())) {
			completedCalls.put(customer.getPhoneNumber(), new ArrayList<Call>());
		}
		return completedCalls.get(customer.getPhoneNumber());
	}

}
